package org.liveboardgames.agricola.control.delegates.action.check
{
    import org.liveboardgames.agricola.control.delegates.action.prerequisite.PrerequisiteChecker;
    import org.liveboardgames.agricola.control.delegates.action.prerequisite.PrerequisiteFactory;
    import org.liveboardgames.agricola.control.delegates.helper.GameHelper;
    import org.liveboardgames.agricola.model.enums.PrerequisiteActionTypeEnum;
    import org.liveboardgames.agricola.model.enums.PrerequisiteEnum;
    import org.liveboardgames.agricola.vo.action.Action;
    import org.liveboardgames.agricola.vo.player.Player;
    import org.liveboardgames.common.dictionary.collections.IMap;
    import org.liveboardgames.common.utils.collections.ContainUtil;
    
    import mx.collections.ListCollectionView;
    
    /** TODO: handle this via the Command? */
    public class ActionCheck
    {
        /** The player that will try and perform the action. */
        public var player:Player;
        
        /** The action that is being checked. */
        protected var action:Action;
        
        /** The list of actions that have previously been played. */
        public var playedActions:ListCollectionView;
        
        public var exclusiveActions:ListCollectionView;
        
        public function ActionCheck(action:Action, player:Player, playedActions:ListCollectionView, exclusiveActions:ListCollectionView)
        {
            this.player = player;
            this.action = action;
            this.playedActions = playedActions;
            this.exclusiveActions = exclusiveActions;
        }
        
        /**
         * The method that performs standard validation. It can
         * be overridden for more custom checks.
         */
        public function isActionAllowed():Boolean
        {
            var actionAllowed:Boolean = true;
            
            // Check prerequisites
            var prerequisiteEnums:ListCollectionView = action.prerequisiteEnums;
            
            // Check prerequisites that are not actions
            if (prerequisiteEnums != null && prerequisiteEnums.length > 0)
            {
                for each (var prerequisite:Object in prerequisiteEnums)
                {
                    if (prerequisite is String)
                    {
                        var prereq:String = prerequisite as String;
                        var prerequisiteChecker:PrerequisiteChecker = PrerequisiteFactory.getPrerequisiteChecker(prereq,
                            player);
                        var prereqMet:Boolean = prerequisiteChecker.check();
                        actionAllowed = actionAllowed && prereqMet;
                    }
                }
            }
            
            // TODO: refactor this to get rid of the getPrerequisiteActions method
            // Check prerequisite actions
            var prerequisiteActions:ListCollectionView = action.getPrerequisiteActions();
            
            if (prerequisiteActions != null && prerequisiteActions.length > 0)
            {
                var prerequisiteType:String = action.prerequisiteActionType;
                var prereqActionMet:Boolean = false;
                
                // Check that at least one action in the list of prerequisites is part of the played actions
                if (PrerequisiteActionTypeEnum.ANY == prerequisiteType)
                {
                    for each (var prerequisiteAction:Action in prerequisiteActions)
                    {
                        if (playedActions != null && (ContainUtil.getActionIndex(playedActions, prerequisiteAction) != -1))
                        {
                            prereqActionMet = true;
                        }
                        else
                        {
                            trace("played actions does not contain " + prerequisiteAction);
                        }
                    }
                }
                actionAllowed = actionAllowed && prereqActionMet;
            }
            
            // Check that no exclusive action has been performed
            if (exclusiveActions != null)
            {
                for each (var exclusiveAction:Action in exclusiveActions)
                {
                    if ((ContainUtil.getActionIndex(exclusiveActions, action) != -1) && playedActions != null && (ContainUtil.getActionIndex(playedActions,
                        exclusiveAction) != -1))
                    {
                        actionAllowed = false;
                    }
                }
            }
            
            // Check that the user can afford to pay for at least one use 
            // of the action
            var cost:IMap = action.cost;
            var canPay:Boolean = GameHelper.canPay(player, cost);
            actionAllowed = actionAllowed && canPay;
            //trace("is action " + action + " allowed?" + actionAllowed);
            
            return actionAllowed;
        }
    
    }
}